/*
 * Anything: A flexible and easy to use data structure that combines the 
 * characteristics of a list and a hashmap into one data structure.
 * 
 * Based on a paper by Peter Sommerlad and Marcel Rueedi on 
 * 'Do-it-yourself reflection' entered at EuroPLOP 1998.
 * 
 * This library was written completely from scratch and is based only 
 * in spirit on the original Java Anything implementation written by 
 * Andre Weinand/Marcel Rueedi in 1997/99 and enhanced by Stefan Tramm 
 * in 2006.
 * 
 * Copyright (c) 2008 Thomas Marti and others. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package any.functor.impl.func;

import any.ImmutableAny;
import any.functor.interfaces.DefaultableTargetTypedFromAnyFunction;
import any.impl.util.Utils;


public class AsEnum<E extends Enum<E>> 
	extends BaseDefaultableAsTypeFunction<E,E, AsEnum<E>> 
	implements DefaultableTargetTypedFromAnyFunction<E> {

	@SuppressWarnings("unchecked")
	public AsEnum(E en) throws NullPointerException, IllegalArgumentException {
		this((Class<E>)en.getClass());
	}
	
	public AsEnum(Class<E> enumType) throws NullPointerException, IllegalArgumentException {
		super(enumType);
		if (!Utils.isEnum(enumType)) throw new IllegalArgumentException("Type '" + enumType.getName() + "' is not an Enum!");
	}
	
	@Override
	protected E asType(ImmutableAny from, E defaultValue) {
		String str = from.asString(null);
		if (str != null && str.length() > 0) {
			E result = asEnum(str);		
			if (result != null) return result;
			
			result = asEnum(str.toUpperCase());
			if (result != null) return result;
			
			result = asEnum(str.toLowerCase());
			if (result != null) return result;

			if (str.length() > 1) {
				result = asEnum(toCamelCase(str));
				if (result != null) return result;
			}

		}
		return defaultValue;
	}

	private E asEnum(String str) {
		try {
			return Enum.valueOf(type, str);
		} catch (IllegalArgumentException e) {
			return null;
		}
	}

	private String toCamelCase(String str) {
		return str.substring(0, 1).toUpperCase().concat(str.substring(1).toLowerCase());
	}

	@Override
	public String toStringPrefix() {
		return "AsEnum of " + type.getName();
	}
	
}
